home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_n_z.arj / WC.ASM < prev    next >
Assembly Source File  |  1989-03-20  |  10KB  |  320 lines

  1. cseg    segment
  2.     org 100h
  3.     assume ds:cseg, cs:cseg
  4. ;================================================
  5. ; PROGRAM WC    Version 1.1 by Dave Whitman
  6. ;
  7. ; Filter to count words, lines and characters.
  8. ; Based loosely on Kernighan and Ritchie, page 18.
  9. ;
  10. ; Syntax:  WC [/w] [/l] [/c]
  11. ;
  12. ;          /w = unlabeled word count
  13. ;          /l = unlabeled line count
  14. ;          /c = unlabeled character count
  15. ;        none = combined counts, with labels
  16. ;
  17. ; The three options may be present in any combination.
  18. ; Regardless of option order, the selected counts will
  19. ; be in the following order:
  20. ;    words
  21. ;    lines
  22. ;    characters
  23. ;
  24. ; Requires DOS 2.0, will abort under earlier versions.
  25. ;====================================================
  26.  
  27. ;============
  28. ; Equates
  29. ;============
  30.  
  31. @read   equ    3FH             ;read file/device
  32. @chrin  equ    06H             ;get char from stdin
  33. @chrout equ    02H             ;send char to stdout
  34. @dosver equ    30H             ;get dos version
  35. @prnstr equ    09H             ;print string
  36.  
  37. stdin   equ    0000H           ;standard input
  38. w       equ    01H             ;flag value for word option
  39. l       equ    02H             ;flag value for line option
  40. c       equ    04H             ;flag value for char option
  41. yes     equ    0FFH            ;boolean value
  42. no      equ    00H             ;    "
  43. bsn      equ    0DH             ;newline char
  44. bst      equ    09H             ;tab char
  45. bsl      equ    0AH             ;linefeed char
  46.  
  47. param_count    equ     [80H]
  48. param_area     equ     [81H]
  49.  
  50. main   proc    far
  51.        call    setup           ;check dos, parse options
  52.        call    buf_in          ;count w, l, c from std i/o
  53.        call    output          ;send requested output
  54.        int     20H             ;and return to dos
  55. main   endp
  56.  
  57. ;======================================
  58. ; SUBROUTINE SETUP
  59. ; Checks for proper DOS, parses options
  60. ;======================================
  61. setup  proc    near
  62.  
  63.        mov     ah, @dosver     ;what dos are we under?
  64.        int     21H
  65.        cmp     al, 2           ;2.0 or over?
  66.        jae     a1              ;yes, skip
  67.  
  68.        mov     ah, @prnstr     ;no, bitch
  69.        mov     dx, offset(baddos)
  70.        int     21H
  71.        pop     ax              ;reset stack
  72.        int     20H             ;and exit
  73.  
  74. a1:     xor     ch,ch           ;cx <== param count
  75.        mov     cl, param_count ;  "
  76.        cmp     cl, 00H         ;any params?
  77.        je      aexit           ;exit if none
  78.  
  79.        mov     di, offset(param_area)   ;scan for options
  80. a2:     mov     al, '/'                  ;will be marked with /
  81.        repnz
  82.        scasb
  83.        jnz     aexit           ;reached end
  84.  
  85.        mov     al, [di]        ;get option char
  86.        and     al, 0DFH        ;guarantees upper case
  87.  
  88.        cmp     al, 'W'         ;words?
  89.        jne     a3              ;nope
  90.        orb     options, w      ;yes, set flag
  91.        jmps    a2              ;and loop
  92.  
  93. a3:     cmp     al, 'L'         ;lines?
  94.        jne     a4              ;nope
  95.        orb     options, l      ;yes, set flag
  96.        jmps    a2              ;and loop
  97.  
  98. a4:     cmp     al, 'C'         ;characters?
  99.        jne     a2              ;nope, just loop
  100.        orb     options, c      ;yes, set flag
  101.        jmps    a2              ;and loop
  102.  
  103. aexit:  ret
  104.  
  105. baddos db      'This program requires DOS 2.0!' 0DH, 0AH, '$'
  106. setup    endp
  107.  
  108. ;=========================================
  109. ; SUBROUTINE BUF_INPUT
  110. ; Inputs data by sector, sends it one char
  111. ; at a time for counting.
  112. ;==========================================
  113.  
  114.  
  115. buf_in proc    near
  116.  
  117.        movb    inword, no      ;not currently in a word
  118.  
  119. bu1:    mov     ah, @read       ;read
  120.        mov     bx, stdin       ;from stdin
  121.        mov     cx, 512         ;one sector's worth
  122.        mov     dx, offset(buffer)
  123.        int     21H
  124.        cmp     ax, 00H         ;test for EOF
  125.        jz      buexit          ;if so, done
  126.  
  127.        mov     cx,ax           ;cx <== number chars read
  128.        mov     si, offset(buffer)
  129. bu2:    lodsb                   ;al <== next char from buffer
  130.        call    count           ;update totals
  131.        loop    bu2
  132.        jmps    bu1
  133. buexit: ret
  134. buf_in    endp
  135.  
  136. ;=============================================
  137. ;SUBROUTINE COUNT
  138. ;Counts words, lines and characters as per K&R
  139. ;=============================================
  140. count  proc    near
  141.        addw    clow,0001H      ;bump # of chars
  142.        jae     b1              ;no carry? skip
  143.        incw    chigh           ;handle carry
  144.  
  145.        ;in the following, note use of ADD to increment
  146.        ;doublewords.  INC does not affect Carry Flag.
  147.  
  148. b1:     cmp     al, bsn          ;is it a newline?
  149.        jne     b2              ;no, skip
  150.        addw    llow,0001H      ;bump # of lines
  151.        jae     b2              ;no carry? skip
  152.        incw    lhigh           ;handle carry
  153.  
  154. b2:     cmp     al, bsn          ;newline or
  155.        je      b3
  156.        cmp     al, bst          ;tab or
  157.        je      b3
  158.        cmp     al, bsl          ;linefeed or
  159.        je      b3
  160.        cmp     al, ' '         ;blank,
  161.        je      b3              ;then skip
  162.  
  163.       ;none of the above
  164.        cmpb    inword, yes     ;already in a word?
  165.        je      b4              ;yes, return
  166.        movb    inword, yes     ;if not, we are now.
  167.        addw    wlow,0001H      ;bump word count
  168.        jae     b4              ;no carry? return
  169.        incw    whigh           ;handle carry
  170.        jmps    b4              ;return
  171.  
  172.       ;any of the above
  173. b3:     movb    inword, no
  174. b4:     ret
  175. count    endp
  176.  
  177. ;=====================================
  178. ; SUBROUTINE OUTPUT
  179. ; Prints results, modified by options.
  180. ;=====================================
  181. output proc    near
  182.  
  183.        cmpb    options, 00H    ;any options?
  184.        jne     c1              ;yes, skip label
  185.        mov     ah, @prnstr     ;print label for word count
  186.        mov     dx, offset(word_label)
  187.        int     21H
  188.        jmps    c1a             ;print count
  189.  
  190. c1:     testb   options, W      ;/w option?
  191.        jz      c2              ;nope, skip
  192. c1a:    mov     di, whigh       ;get doubleword word count
  193.        mov     si, wlow        ; in di:si
  194.        call    printdd         ;convert and print it.
  195.        call    newline
  196.  
  197. c2:     cmpb    options, 00H    ;any options?
  198.        jne     c3              ;yes, skip label
  199.        mov     ah, @prnstr     ;print label for line count
  200.        mov     dx, offset(line_label)
  201.        int     21H
  202.        jmps    c3a             ;print count
  203.  
  204. c3     testb   options, L      ;/l option?
  205.        jz      c4              ;nope, skip
  206. c3a    mov     di, lhigh       ;get doubleword line count
  207.        mov     si, llow        ; in di:si
  208.        call    printdd         ;convert and print it
  209.        call    newline
  210.  
  211. c4:     cmpb    options, 00H    ;any options?
  212.        jne     c5              ;yes, skip label
  213.        mov     ah, @prnstr     ;print label for char count
  214.        mov     dx, offset(char_label)
  215.        int     21H
  216.        jmps    c5a             ;print count
  217.  
  218. c5:     testb   options, C      ;/c option?
  219.        jz      c6              ;nope, skip
  220. c5a:    mov     di, chigh       ;get doubleword char count
  221.        mov     si, clow        ; in di:si
  222.        call    printdd         ;convert and print it
  223.        call    newline
  224.  
  225. c6:     ret
  226.  
  227. word_label db 'Words:  $'
  228. line_label db 'Lines:  $'
  229. char_label db 'Chars:  $'
  230. output    endp
  231.  
  232. ;=========================
  233. ; SUBROUTINE NEWLINE
  234. ; Prints a CR/LF to stdout
  235. ;=========================
  236. newline proc   near
  237.        mov     ah, @prnstr
  238.        mov     dx, offset(crlf)
  239.        int     21H
  240.        ret
  241. crlf   db      0DH, 0AH, '$'
  242. newline    endp
  243.  
  244. ;=========================================================
  245. ; SUBROUTINE PRINTDD
  246. ; This less-than-comprehensible routine was swiped verbatim
  247. ; from Ted Reuss's disassembly of John Chapman's sorted
  248. ; disk directory program.  The routine converts a 32 bit
  249. ; integer in DI:SI to ASCII digits and sends them to STDOUT.
  250. ;==========================================================
  251.  
  252. PRINTDD PROC    NEAR    ;Prints a 32 bit integer in DI:SI
  253.         XOR     AX,AX           ;Zero out the
  254.         MOV     BX,AX           ; working
  255.         MOV     BP,AX           ; registers.
  256.         MOV     CX,32           ;# bits of precision
  257. J1:      SHL     SI
  258.         RCL     DI
  259.         XCHG    BP,AX
  260.         CALL    J6
  261.         XCHG    BP,AX
  262.         XCHG    BX,AX
  263.         CALL    J6
  264.         XCHG    BX,AX
  265.         ADC     AL,0
  266.         LOOP    J1
  267.         MOV     CX,1710H        ;5904 ?
  268.         MOV     AX,BX
  269.         CALL    J2
  270.         MOV     AX,BP
  271. J2:      PUSH    AX
  272.         MOV     DL,AH
  273.         CALL    J3
  274.         POP     DX
  275. J3:      MOV     DH,DL
  276.         SHR     DL              ;Move high
  277.         SHR     DL              ; nibble to
  278.         SHR     DL              ; the low
  279.         SHR     DL              ; position.
  280.         CALL    J4
  281.         MOV     DL,DH
  282. J4:      AND     DL,0FH          ;Mask low nibble
  283.         JZ      J5              ;If not zero
  284.         MOV     CL,0
  285. J5:      DEC     CH
  286.         AND     CL,CH
  287.         OR      DL,'0'          ;Fold in ASCII zero
  288.         SUB     DL,CL
  289.  
  290.         MOV     AH, @CHROUT     ;Print next digit
  291.         INT     21H
  292.  
  293.         RET                     ;Exit to caller
  294. PRINTDD    ENDP
  295.  
  296. J6     PROC    NEAR
  297.         ADC     AL,AL
  298.         DAA
  299.         XCHG    AL,AH
  300.         ADC     AL,AL
  301.         DAA
  302.         XCHG    AL,AH
  303.         RET
  304. J6    ENDP
  305.  
  306. ;=================
  307. ;GLOBAL VARIABLES
  308. ;=================
  309. options  db  00H       ;byte of option flags
  310. inword   db  00H       ;flag: yes indicates scan is within a word
  311. wlow     db  00H, 00H  ;low part of doubleword word count
  312. whigh    db  00H, 00H  ;high "   "      "       "     "
  313. llow     db  00H, 00H  ;low part of doubleword line count
  314. lhigh    db  00H, 00H  ;high "   "      "       "     "
  315. clow     db  00H, 00H  ;low part of doubleword char count
  316. chigh    db  00H, 00H  ;high "   "      "       "     "
  317. buffer                 ;input buffer
  318. cseg    ends
  319.     end    main
  320.